package com.niiwoo.civet.trade.service.dubbo.kaola;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dto.common.BankCardDTO;
import com.niiwoo.civet.account.service.bankcard.BankCardDubboService;
import com.niiwoo.civet.trade.dao.entity.Project;
import com.niiwoo.civet.trade.dao.entity.ProjectBorrowerPlanNew;
import com.niiwoo.civet.trade.dao.entity.ProjectBorrowerSummary;
import com.niiwoo.civet.trade.dao.mapper.ProjectBorrowerPlanNewMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectBorrowerSummaryMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectMapperExt;
import com.niiwoo.civet.trade.dto.PrepaymentAmountDTO;
import com.niiwoo.civet.trade.dto.kaola.request.BankCardChangeRequest;
import com.niiwoo.civet.trade.dto.kaola.response.BaseResponse;
import com.niiwoo.civet.trade.dto.request.kaola.KaoLaLiCaiRepayRequestDTO;
import com.niiwoo.civet.trade.dto.request.myloan.MyProjectRequestDTO;
import com.niiwoo.civet.trade.dto.response.kaola.KaoLaLiCaiFullRepayResponseDTO;
import com.niiwoo.civet.trade.dto.response.kaola.KaoLaLiCaiImmediateRepayResponseDTO;
import com.niiwoo.civet.trade.dto.response.kaola.KaoLaLiCaiRepayResponseDTO;
import com.niiwoo.civet.trade.enums.ChannelCodeEnum;
import com.niiwoo.civet.trade.enums.ProjectStatusEnum;
import com.niiwoo.civet.trade.enums.RepayStatusEnum;
import com.niiwoo.civet.trade.enums.kaola.KaoLaLiCaiIsPassiveEnum;
import com.niiwoo.civet.trade.enums.kaola.KaoLaRepayOrderRepayTypeEnum;
import com.niiwoo.civet.trade.service.koala.KaoLaLiCaiDubboService;
import com.niiwoo.civet.trade.service.local.kaola.KaoLaLiCaiRepayOrderService;
import com.niiwoo.civet.trade.service.local.kaola.KaoLaLiCaiRepaymentService;
import com.niiwoo.civet.trade.service.local.kaola.KaoLaLiCaiRequestServiceImpl;
import com.niiwoo.tripod.consumer.helper.Assert;
import com.niiwoo.tripod.provider.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * @author lichuanzhi
 * @date 2018/01/11
 */
@Slf4j
@Service(version = "1.0.0",validation = "true")
public class KaoLaLiCaiDubboServiceImpl implements KaoLaLiCaiDubboService {

    @Autowired
    private ProjectBorrowerSummaryMapperExt projectBorrowerSummaryMapper;
    @Autowired
    private ProjectBorrowerPlanNewMapperExt projectBorrowerPlanMapper;
    @Autowired
    private ProjectMapperExt projectMapper;

    @Autowired
    private KaoLaLiCaiRepaymentService kaoLaLiCaiRepaymentService;
    @Autowired
    private KaoLaLiCaiRepayOrderService repayOrderService;
    @Autowired
    private KaoLaLiCaiRequestServiceImpl kaoLaLiCaiRequestService;

    @Reference(version = "1.0.0")
    private BankCardDubboService bankCardDubboService;

    @Override
    public KaoLaLiCaiRepayResponseDTO repayment(KaoLaLiCaiRepayRequestDTO dto) {
        log.info("考拉理财还款 ---,dto="+ JSON.toJSONString(dto));
        KaoLaLiCaiRepayResponseDTO responseDTO = null;
        switch (dto.getType()) {
            //立即还款(正常还款)
            case 0: {
                responseDTO = repayOrderService.repayment(dto, KaoLaRepayOrderRepayTypeEnum.REPAY_NOMAL, KaoLaLiCaiIsPassiveEnum.REPAY_ACTIVE);
                break;
            }
            //提前结清
            case 1: {
                responseDTO = repayOrderService.repayment(dto, KaoLaRepayOrderRepayTypeEnum.REPAY_SETTLE, KaoLaLiCaiIsPassiveEnum.REPAY_ACTIVE);
                break;
            }
            //逾期还款
            case 2: {
                ProjectBorrowerSummary summary = kaoLaLiCaiRepaymentService.getProjectBorrowerSummary(dto.getProjectId());
                RepayStatusEnum repayStatusEnum = RepayStatusEnum.enumOf(summary.getRepayStatus());
                responseDTO = repayOrderService.repayment(dto,
                        RepayStatusEnum.BADLOANS == repayStatusEnum ? KaoLaRepayOrderRepayTypeEnum.REPAY_BADLOANS : KaoLaRepayOrderRepayTypeEnum.REPAY_OVERDUE,
                        KaoLaLiCaiIsPassiveEnum.REPAY_ACTIVE);
                break;
            }
            default:
        }
        return responseDTO;
    }

    @Override
    public KaoLaLiCaiImmediateRepayResponseDTO immediateRepay(MyProjectRequestDTO dto) {
        Long projectId = dto.getProjectId();
        Assert.notNull(projectId,"projectId may not be null");

        //获取标的还款概要信息
        ProjectBorrowerSummary summary = Optional.ofNullable(projectBorrowerSummaryMapper.selectByPrimaryKey(projectId))
                .orElseThrow(() -> new BizException("TRD20001"));
        ProjectBorrowerPlanNew projectBorrowerPlan = Optional.ofNullable(projectBorrowerPlanMapper.selectByProjectAndPeriod(summary.getProjectId(), summary.getCurrentPeriod()))
                .orElseThrow(() -> new BizException("TRD20005"));
        BigDecimal allAmount = kaoLaLiCaiRepaymentService.getImmediateRepayAmount(summary);
        KaoLaLiCaiImmediateRepayResponseDTO refundInfoDTO= new KaoLaLiCaiImmediateRepayResponseDTO();
        refundInfoDTO.setAmount(allAmount);
        refundInfoDTO.setCurrentPeriod(projectBorrowerPlan.getPeriod());
        refundInfoDTO.setTotalPeriod(projectBorrowerPlan.getTotalPeriod());
        refundInfoDTO.setRefundDate(projectBorrowerPlan.getRefundDate());
        refundInfoDTO.setProjectId(projectId);
        refundInfoDTO.setRefundStatus(projectBorrowerPlan.getStatus());
        refundInfoDTO.setOverdueDays(kaoLaLiCaiRepaymentService.getKaolaOverdueDays(projectBorrowerPlan.getRefundDate(), false));
        refundInfoDTO.setRepayStatus(summary.getRepayStatus());
        refundInfoDTO.setCanRefund(repayOrderService.isProcessing(projectId).getCode());
        return refundInfoDTO;
    }

    @Override
    public KaoLaLiCaiFullRepayResponseDTO fullRepay(MyProjectRequestDTO dto) {
        Long projectId = dto.getProjectId();
        Assert.notNull(projectId,"projectId may not be null");

        //获取标的还款概要信息
        ProjectBorrowerSummary summary = Optional.ofNullable(projectBorrowerSummaryMapper.selectByPrimaryKey(projectId))
                .orElseThrow(() -> new BizException("TRD20001"));
        PrepaymentAmountDTO prepaymentAmount = kaoLaLiCaiRepaymentService.calcNiiWooPreRePay(summary, false);
        KaoLaLiCaiFullRepayResponseDTO responseDTO= new KaoLaLiCaiFullRepayResponseDTO();
        responseDTO.setRepaymentTotalAmount(prepaymentAmount.getPrincipal().add(prepaymentAmount.getInterest())
                .add(prepaymentAmount.getPlatformManagerFee()).add(prepaymentAmount.getCreditGuaranteeFee()));
        responseDTO.setRepaymentCapitalTotal(prepaymentAmount.getPrincipal());
        responseDTO.setCurrentPeriodInterest(prepaymentAmount.getInterest());
        responseDTO.setRepaymentManagementFeeTotal(prepaymentAmount.getPlatformManagerFee());
        responseDTO.setRepaymentGuaranteeFeeTotal(prepaymentAmount.getCreditGuaranteeFee());
        responseDTO.setEconomizeAmount(prepaymentAmount.getCutCosts());
        responseDTO.setCanRefund(repayOrderService.isProcessing(projectId).getCode());
        return responseDTO;
    }


    @Override
    public boolean bankCardChange(@NotBlank(message = "userId may not be null") String userId) {
        BankCardDTO userBankCardInfo = bankCardDubboService.getUserBankCardInfo(userId);
        BankCardChangeRequest request = new BankCardChangeRequest();
        request.setIdCard(userBankCardInfo.getIdCard().toUpperCase());
        request.setBankcardNo(userBankCardInfo.getBankAccountNo());
        request.setMobile(userBankCardInfo.getMobileNo());
        BaseResponse baseResponse = kaoLaLiCaiRequestService.bankCardChange(request);
        if (!baseResponse.isSuccess()) {
            throw new BizException("TRD21003", baseResponse.getMsg());
        }
        return true;
    }

    @Override
    public KaoLaLiCaiImmediateRepayResponseDTO getRepayingProjectByUserId(@NotBlank(message = "userId may not be null") String userId) {
        Optional<Project> project = projectMapper.listProjectByChannelCodeAndStatus(userId, ChannelCodeEnum.KAOLA.getChanelCode(), Collections
                .singletonList(ProjectStatusEnum.REPAYING), null).stream().findFirst();
        if (project.isPresent()) {
            MyProjectRequestDTO requestDTO = new MyProjectRequestDTO();
            requestDTO.setProjectId(project.get().getProjectId());
            try {
                KaoLaLiCaiImmediateRepayResponseDTO responseDTO = this.immediateRepay(requestDTO);
                responseDTO.setBankCard(this.getIdCard(userId));
                return responseDTO;
            } catch (Exception e) {
                log.error("考拉理财**获取立即还款相关信息异常",e);
            }
        }
        return null;
    }

    /**
     * 获取指定用户银行卡号后四位
     * @param userId 用户id
     * @return 银行卡号后四位
     */
    private String getIdCard(String userId) {
        return Optional.ofNullable(bankCardDubboService.getUserBankCardInfo(userId)).map(r -> StringUtils.substring(r.getBankAccountNo(),-4)).orElse(null);
    }

    /**
     * 处理逾期和正常还款的，查询状态为正常还款和逾期还款中的标的且还款日小于等于当前日期
     */
    @Override
    public void scheduleWithhold() {
        List<ProjectBorrowerSummary> summaries = projectBorrowerSummaryMapper.scheduleWithhold();
        log.info("考拉自动代扣计划任务##开始，待代扣标的数:{}", summaries.size());
        Long start = System.currentTimeMillis();
        summaries.parallelStream().forEach(summary -> {
            RepayStatusEnum repayStatusEnum = RepayStatusEnum.enumOf(summary.getRepayStatus());
            KaoLaLiCaiRepayRequestDTO repayRequestDTO = new KaoLaLiCaiRepayRequestDTO();
            repayRequestDTO.setUserId(summary.getBorrowerUserId());
            repayRequestDTO.setProjectId(summary.getProjectId());
            try {
                repayOrderService.repayment(repayRequestDTO,
                        RepayStatusEnum.NORMAL == repayStatusEnum ? KaoLaRepayOrderRepayTypeEnum.REPAY_NOMAL
                                : RepayStatusEnum.OVERDUE == repayStatusEnum ? KaoLaRepayOrderRepayTypeEnum.REPAY_OVERDUE
                                : KaoLaRepayOrderRepayTypeEnum.REPAY_BADLOANS,
                        KaoLaLiCaiIsPassiveEnum.REPAY_PASSIVE, summary);
            } catch (Exception e) {
                log.error("考拉标的:{},代扣计划任务异常,userId:{}", summary.getProjectId(), summary.getBorrowerUserId(), e);
            }
        });
        log.info("考拉自动代扣计划任务##结束,耗时:{}", System.currentTimeMillis() - start);
    }
}
